package service

import (
	"context"
	"errors"
	"pmservice/db"
	"pmservice/graph/model"
)

func (s *Service) PocNew(ctx context.Context, input model.PocNew) (*model.PointOfCare, error) {
	hos := db.HospitalGet(s.Orm.DB, input.Hosuid)
	if hos == nil {
		return nil, errors.New("hos not found")
	}

	fac := db.FacGet(s.Orm.DB, input.Facuid)
	if fac == nil {
		return nil, errors.New("fac not found")
	}

	if fac.Hospital != input.Hosuid {
		return nil, errors.New("fac not co-exist with hos")
	}

	if db.PocExist(s.Orm.DB, input.Hosuid, "", input.Code) {
		return nil, errors.New("病床编号已被使用")
	}

	d, err := db.PocNew(s.Orm.DB, &input)
	if err != nil {
		return nil, errors.New("poc create failed")
	}

	return s.PocGet(ctx, d.UID, "")
}

func (s *Service) PocSave(ctx context.Context, uid string, input model.PocEdit) (bool, error) {
	poc := db.PocGet(s.Orm.DB, uid)
	if poc == nil {
		return false, errors.New("poc not found")
	}

	if input.Code != nil && db.PocExist(s.Orm.DB, poc.Hospital, uid, *input.Code) {
		return false, errors.New("code used")
	}

	return db.PocSave(s.Orm.DB, uid, &input), nil
}

func (s *Service) PocDelete(ctx context.Context, uid string) (bool, error) {
	return db.PocDel(s.Orm.DB, uid), nil
}

func (s *Service) PocInstallEcm(ctx context.Context, uid string, ecmuid string) (bool, error) {
	ecm := db.EcmGet(s.Orm.DB, ecmuid)
	if ecm == nil {
		return false, errors.New("ecm not found")
	}
	poc := db.PocGetByInstalledEcm(s.Orm.DB, ecmuid)
	if poc != nil && poc.UID != uid {
		return false, errors.New("ecm has been installed already")
	}

	return db.PocInstallEcm(s.Orm.DB, uid, ecmuid), nil
}

func (s *Service) PocUninstallEcm(ctx context.Context, uid string, ecmuid string) (bool, error) {
	return db.PocUninstallEcm(s.Orm.DB, uid, ecmuid), nil
}

func (s *Service) PocGetCompositeData(ctx context.Context, d *db.Poc, prefix string) (*model.PointOfCare, error) {
	ret := d.ToGQL()
	if HasField(ctx, PrefixJoin(prefix, "hospital")) {
		ret.Hospital, _ = s.HospitalGet(ctx, d.Hospital, PrefixJoin(prefix, "hospital"))
	}

	if HasField(ctx, PrefixJoin(prefix, "facility")) {
		ret.Facility, _ = s.FacGet(ctx, d.Facility, PrefixJoin(prefix, "facility"))
	}

	if HasField(ctx, PrefixJoin(prefix, "ecm")) && d.ECM.Valid {
		ret.Ecm, _ = s.EcmGet(ctx, d.ECM.String, PrefixJoin(prefix, "ecm"))
	}

	return ret, nil
}

func (s *Service) PocAdmitPatient(ctx context.Context, uid string, input *model.PatientEdit) bool {
	return db.PocAdmitPatient(s.Orm.DB, uid, input)
}

func (s *Service) PocDischargePatient(ctx context.Context, uid string) bool {
	return db.PocDischargePatient(s.Orm.DB, uid)
}

func (s *Service) PocGet(ctx context.Context, uid string, prefix string) (*model.PointOfCare, error) {
	d := db.PocGet(s.Orm.DB, uid)
	if d == nil {
		return nil, errors.New("poc not found")
	}

	return s.PocGetCompositeData(ctx, d, prefix)
}

func (s *Service) PocGetByInstalledEcm(ctx context.Context, ecmuid string, prefix string) (*model.PointOfCare, error) {
	d := db.PocGetByInstalledEcm(s.Orm.DB, ecmuid)
	if d == nil {
		return nil, nil
	}

	return s.PocGetCompositeData(ctx, d, prefix)
}

func (s *Service) PocSearch(ctx context.Context, cond model.PocSearchCond, prefix string) (*model.PocSearchResult, error) {
	pocs, total := db.PocSearch(s.Orm.DB, cond)
	ret := model.PocSearchResult{
		Results: make([]*model.PointOfCare, 0),
		Total:   int(total),
	}

	for _, p := range pocs {
		poc, _ := s.PocGetCompositeData(ctx, p, prefix)
		if poc != nil {
			ret.Results = append(ret.Results, poc)
		}
	}

	return &ret, nil
}
